package com.ruyiadmin.springboot.controller.system;

import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.ruyiadmin.springboot.common.annotations.core.AllowAnonymous;
import com.ruyiadmin.springboot.common.annotations.system.Log;
import com.ruyiadmin.springboot.common.annotations.system.Permission;
import com.ruyiadmin.springboot.common.beans.system.SystemCacheConfig;
import com.ruyiadmin.springboot.common.beans.system.SystemConfig;
import com.ruyiadmin.springboot.common.beans.system.SystemRedisConfig;
import com.ruyiadmin.springboot.common.components.core.RuYiRedisComponent;
import com.ruyiadmin.springboot.common.components.core.RuYiSessionContext;
import com.ruyiadmin.springboot.common.core.business.enums.DeletionType;
import com.ruyiadmin.springboot.common.core.business.enums.OperationType;
import com.ruyiadmin.springboot.common.core.business.enums.YesNo;
import com.ruyiadmin.springboot.common.core.system.entities.*;
import com.ruyiadmin.springboot.common.core.system.enums.DataType;
import com.ruyiadmin.springboot.common.core.system.enums.MessageType;
import com.ruyiadmin.springboot.common.core.system.enums.QueryMethod;
import com.ruyiadmin.springboot.common.utils.core.RuYiAesUtil;
import com.ruyiadmin.springboot.common.utils.core.RuYiFileUtil;
import com.ruyiadmin.springboot.common.utils.core.RuYiPoiUtil;
import com.ruyiadmin.springboot.common.utils.core.RuYiRsaUtil;
import com.ruyiadmin.springboot.domain.dto.system.*;
import com.ruyiadmin.springboot.domain.entity.system.SysOrgUser;
import com.ruyiadmin.springboot.domain.entity.system.SysUser;
import com.ruyiadmin.springboot.service.iservices.system.ISysImportConfigService;
import com.ruyiadmin.springboot.service.iservices.system.ISysOrgUserService;
import com.ruyiadmin.springboot.service.iservices.system.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.modelmapper.ModelMapper;
import org.springframework.http.HttpStatus;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.jms.Topic;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统用户 前端控制器
 * </p>
 *
 * @author RuYiAdmin
 * @since 2022-06-28
 */
@RestController
@RequestMapping("/UserManagement")
@Api(tags = "系统用户管理服务")
@RequiredArgsConstructor
public class SysUserController {

    //region 服务私有属性

    private final RuYiRedisComponent redisUtils;
    private final SystemCacheConfig systemCacheConfig;
    private final ISysUserService userService;
    private final ISysOrgUserService orgUserService;
    private final RuYiSessionContext sessionContext;
    private final ModelMapper modelMapper;
    private final SystemConfig systemConfig;
    private final SystemRedisConfig systemRedisConfig;
    private final Topic topic;
    private final JmsMessagingTemplate jmsMessagingTemplate;
    private final ISysImportConfigService importConfigService;

    //endregion

    //region 查询用户列表

    @PostMapping("/Post")
    @ApiOperation(value = "查询用户列表")
    @Log(OperationType = OperationType.QueryList)
    @Permission(permission = "user:query:list")
    public QueryResult<SysUserDTO> queryOrgUserInfo(@RequestBody QueryCondition queryCondition) throws Exception {
        if (queryCondition.getQueryItems().size() <= 0) {
            queryCondition.setQueryItems(new ArrayList<>());
            String orgId = this.sessionContext.getUserOrgId();
            queryCondition.getQueryItems().add(new QueryItem("ORG_ID", DataType.Guid, QueryMethod.Equal, orgId));
        }
        return this.userService.queryOrgUserInfo(queryCondition);
    }

    //endregion

    //region 查询用户信息

    @GetMapping("/GetById/{userId}")
    @ApiOperation(value = "查询用户信息")
    @Log(OperationType = OperationType.QueryEntity)
    @Permission(permission = "user:query:list")
    public ActionResult getById(@PathVariable("userId") String userId)
            throws ExecutionException, InterruptedException {
        CompletableFuture<ActionResult> future = CompletableFuture.supplyAsync(() -> {
            Object value = this.redisUtils.get(systemCacheConfig.getUserCacheName());
            List<SysUserDTO> users = JSON.parseArray(value.toString(), SysUserDTO.class);
            SysUserDTO user = users.stream()
                    .filter(t -> t.getId().equals(userId))
                    .collect(Collectors.toList())
                    .get(0);
            return ActionResult.success(user);
        });
        return future.get();
    }

    //endregion

    //region 用户登录名检测

    @GetMapping("/IsExistedLogonName/{logonName}")
    @ApiOperation(value = "用户登录名检测")
    @Log(OperationType = OperationType.QueryEntity)
    @Permission(permission = "user:add:entity")
    public ActionResult isExistedLogonName(@PathVariable("logonName") String logonName)
            throws ExecutionException, InterruptedException {
        CompletableFuture<ActionResult> future = CompletableFuture.supplyAsync(() -> {
            List<SysUser> allUsers = this.userService.queryAllUsers();
            long size = allUsers.stream()
                    .filter(t -> t.getLogonName().equals(logonName))
                    .count();
            return ActionResult.success(size > 0);
        });
        return future.get();
    }

    //endregion

    //region 新增用户信息

    @PostMapping("/Add")
    @ApiOperation(value = "新增用户信息")
    @Log(OperationType = OperationType.AddEntity)
    @Permission(permission = "user:add:entity")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult add(@Valid @RequestBody SysUserDTO userDTO) {
        String orgId = userDTO.getOrgId();
        String orgName = userDTO.getOrgName();

        String defaultPassword = this.systemConfig.getDefaultPassword();
        String aesKey = this.systemConfig.getAesKey();

        String salt = UUID.randomUUID().toString();
        userDTO.setSalt(salt);
        userDTO.setPassword(RuYiAesUtil.encrypt(defaultPassword + salt, aesKey));

        //region 新增机构与用户关系

        //DTO TO POJO
        SysUser user = this.modelMapper.map(userDTO, SysUser.class);
        //新增用户
        this.userService.save(user);

        //用户与机构关联
        SysOrgUser orgUser = new SysOrgUser();
        orgUser.setOrgId(orgId);
        orgUser.setUserId(user.getId());
        this.orgUserService.save(orgUser);

        //endregion

        //region 数据一致性维护

        userDTO = this.modelMapper.map(user, SysUserDTO.class);
        userDTO.setOrgId(orgId);
        userDTO.setOrgName(orgName);

        //获取用户缓存
        Object value = this.redisUtils.get(systemCacheConfig.getUserCacheName());
        List<SysUserDTO> users = JSON.parseArray(value.toString(), SysUserDTO.class);
        //添加新数据
        users.add(userDTO);
        //更新用户缓存
        this.redisUtils.set(systemCacheConfig.getUserCacheName(), JSON.toJSONString(users));

        //endregion

        return ActionResult.success(userDTO);
    }

    //endregion

    //region 编辑用户信息

    @PutMapping("/Put")
    @ApiOperation(value = "编辑用户信息")
    @Log(OperationType = OperationType.EditEntity)
    @Permission(permission = "user:edit:entity")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult edit(@Valid @RequestBody SysUserDTO userDTO) throws Exception {
        //原始用户信息
        SysUser origin = this.userService.getById(userDTO.getId());

        //密钥
        String rsaPriKey = this.systemConfig.getRsaPrivateKey();
        String aesKey = this.systemConfig.getAesKey();

        //更换用户密码
        userDTO.setPassword(RuYiRsaUtil.decrypt(userDTO.getPassword(), rsaPriKey));
        if (!origin.getPassword().equals(userDTO.getPassword())) {
            String salt = UUID.randomUUID().toString();
            userDTO.setSalt(salt);
            userDTO.setPassword(RuYiAesUtil.encrypt(userDTO.getPassword() + salt, aesKey));
        }

        String orgId = userDTO.getOrgId();
        String orgName = userDTO.getOrgName();

        //DTO TO POJO
        SysUser user = this.modelMapper.map(userDTO, SysUser.class);
        //修改用户
        this.userService.updateById(user);

        if (user.getIsEnabled() == 0) {
            //region 强制禁用用户下线

            String pattern = String.format("%s%s_*", systemRedisConfig.getPattern(), user.getId());
            List<String> keys = this.redisUtils.scan(pattern);
            if (keys.size() > 0) {
                for (String item : keys) {
                    //删除用户token
                    this.redisUtils.del(item);
                }
            }

            SystemMessage msg = new SystemMessage();
            msg.setMessage("ForceLogout");
            msg.setMessageType(MessageType.ForceLogout);
            msg.setObject(user);

            this.jmsMessagingTemplate.convertAndSend(topic, JSON.toJSONString(msg));

            //endregion
        }

        //region 数据一致性维护

        userDTO = this.modelMapper.map(user, SysUserDTO.class);
        userDTO.setOrgId(orgId);
        userDTO.setOrgName(orgName);

        //获取用户缓存
        Object value = this.redisUtils.get(systemCacheConfig.getUserCacheName());
        List<SysUserDTO> users = JSON.parseArray(value.toString(), SysUserDTO.class);

        //删除旧数据
        for (Iterator<SysUserDTO> iterator = users.iterator(); iterator.hasNext(); ) {
            SysUserDTO element = iterator.next();
            if (element.getId().equals(userDTO.getId())) {
                iterator.remove();
                break;
            }
        }
        //添加新数据
        users.add(userDTO);
        //更新用户缓存
        this.redisUtils.set(systemCacheConfig.getUserCacheName(), JSON.toJSONString(users));

        //更新机构的管理人姓名
        if (!origin.getDisplayName().equals(userDTO.getDisplayName())) {
            //获取机构缓存
            value = this.redisUtils.get(this.systemCacheConfig.getOrgCacheName());
            List<SysOrganizationDTO> orgs = JSON.parseArray(value.toString(), SysOrganizationDTO.class);

            String leader = userDTO.getId();
            List<SysOrganizationDTO> subs = orgs.stream().
                    filter(t -> !StringUtils.isEmpty(t.getLeader())).
                    filter(t -> t.getLeader().equals(leader)).
                    collect(Collectors.toList());

            for (SysOrganizationDTO item : subs) {
                //删除旧数据
                for (Iterator<SysOrganizationDTO> iterator = orgs.iterator(); iterator.hasNext(); ) {
                    SysOrganizationDTO element = iterator.next();
                    if (element.getId().equals(item.getId())) {
                        iterator.remove();
                        break;
                    }
                }

                //更新机构管理人姓名
                item.setLeaderName(userDTO.getDisplayName());
                orgs.add(item);
            }

            //更新机构缓存
            this.redisUtils.set(this.systemCacheConfig.getOrgCacheName(), JSON.toJSONString(orgs));

        }

        //endregion

        return ActionResult.success(userDTO);
    }

    //endregion

    //region 批量删除用户信息

    @DeleteMapping("/DeleteRange/{ids}")
    @ApiOperation(value = "批量删除用户信息")
    @Log(OperationType = OperationType.DeleteEntity)
    @Permission(permission = "user:del:entities")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult deleteRange(@PathVariable("ids") String ids) {
        //删除用户
        List<String> array = Arrays.asList(ids.split(","));
        ActionResult actionResult = ActionResult.success(this.userService.removeByIds(array));

        array.forEach(item -> {
            //获取用户与机构关系
            List<SysOrgUser> orgUsers = this.orgUserService.list().stream().
                    filter(t -> t.getIsdel() == DeletionType.Undeleted.ordinal()).
                    filter(t -> t.getUserId().equals(item)).
                    collect(Collectors.toList());
            //解除用户与机构关系
            orgUsers.forEach(x -> {
                this.orgUserService.removeById(x.getId());
            });
        });

        //region 数据一致性维护

        //获取用户缓存
        Object value = this.redisUtils.get(systemCacheConfig.getUserCacheName());
        List<SysUserDTO> users = JSON.parseArray(value.toString(), SysUserDTO.class);

        array.forEach(item -> {
            //删除旧数据
            for (Iterator<SysUserDTO> iterator = users.iterator(); iterator.hasNext(); ) {
                SysUserDTO element = iterator.next();
                if (element.getId().equals(item)) {
                    //region 强制禁用用户下线

                    String pattern = String.format("%s%s_*", systemRedisConfig.getPattern(), item);
                    List<String> keys = this.redisUtils.scan(pattern);
                    if (keys.size() > 0) {
                        for (String key : keys) {
                            //删除用户token
                            this.redisUtils.del(key);

                            SystemMessage msg = new SystemMessage();
                            msg.setMessage("ForceLogout");
                            msg.setMessageType(MessageType.ForceLogout);
                            msg.setObject(element);

                            this.jmsMessagingTemplate.convertAndSend(topic, JSON.toJSONString(msg));
                        }
                    }

                    //endregion
                    iterator.remove();
                    break;
                }
            }
        });

        //endregion

        return actionResult;
    }

    //endregion

    //region 用户登录系统

    @PostMapping("/Logon")
    @ApiOperation(value = "用户登录系统")
    @AllowAnonymous
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult add(@RequestBody @Valid LoginDTO loginDTO) throws Exception {
        return this.userService.logon(loginDTO);
    }

    //endregion

    //region 用户退出登录

    @GetMapping("/Logout/{token}")
    @ApiOperation(value = "用户退出登录")
    @Log(OperationType = OperationType.Logout)
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult userLogout(@PathVariable("token") String token) {
        return this.userService.userLogout(token);
    }

    //endregion

    //region 强制用户退出

    @GetMapping("/ForceLogout/{token}")
    @ApiOperation(value = "强制用户退出")
    @Log(OperationType = OperationType.ForceLogout)
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult forceUserLogout(@PathVariable("token") String token) throws Exception {
        return this.userService.forceUserLogout(token);
    }

    //endregion

    //region 按机构获取用户

    @GetMapping("/GetUserByOrgId/{orgId}")
    @ApiOperation(value = "按机构获取用户")
    @Log(OperationType = OperationType.QueryList)
    public QueryResult<SysUserDTO> getUserByOrgId(@PathVariable("orgId") String orgId)
            throws ExecutionException, InterruptedException {
        CompletableFuture<QueryResult<SysUserDTO>> future = CompletableFuture.supplyAsync(() -> {
            Object value = this.redisUtils.get(this.systemCacheConfig.getUserCacheName());
            List<SysUserDTO> users = JSON.parseArray(value.toString(), SysUserDTO.class);
            users = users.stream().
                    filter(t -> !StringUtils.isEmpty(t.getOrgId())).
                    filter(t -> t.getOrgId().equals(orgId)).
                    collect(Collectors.toList());
            return QueryResult.success(users.size(), users);
        });
        return future.get();
    }

    //endregion

    //region 更新用户密码

    @PostMapping("/UpdatePassword")
    @ApiOperation(value = "更新用户密码")
    @Log(OperationType = OperationType.UpdatePassword)
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult updatePassword(@Valid @RequestBody PasswordDTO data) throws Exception {
        String prikey = this.systemConfig.getRsaPrivateKey();//RSA私钥
        String aesKey = this.systemConfig.getAesKey();//AES KEY

        //用户信息解密
        String userId = RuYiRsaUtil.decrypt(data.getUserId(), prikey);
        String password = RuYiRsaUtil.decrypt(data.getPassword(), prikey);
        String salt = RuYiRsaUtil.decrypt(data.getSalt(), prikey);

        //密码去盐
        password = password.replace("_" + salt, "");

        //获取用户信息
        SysUser user = this.userService.getById(userId);
        salt = UUID.randomUUID().toString();
        user.setSalt(salt);
        user.setPassword(RuYiAesUtil.encrypt(password + salt, aesKey));//AES加密
        this.userService.updateById(user);

        //region 数据一致性维护

        //获取用户缓存
        Object value = this.redisUtils.get(systemCacheConfig.getUserCacheName());
        List<SysUserDTO> users = JSON.parseArray(value.toString(), SysUserDTO.class);

        SysUserDTO userDTO = users.stream().filter(t -> t.getId().equals(user.getId()))
                .collect(Collectors.toList()).get(0);

        //删除旧数据
        for (Iterator<SysUserDTO> iterator = users.iterator(); iterator.hasNext(); ) {
            SysUserDTO element = iterator.next();
            if (element.getId().equals(userDTO.getId())) {
                iterator.remove();
                break;
            }
        }

        //更新用户信息
        userDTO.setSalt(user.getSalt());
        userDTO.setPassword(user.getPassword());
        userDTO.setModifier(user.getModifier());
        userDTO.setModifyTime(user.getModifyTime());
        userDTO.setVersionId(user.getVersionId());

        //添加新数据
        users.add(userDTO);

        //更新用户缓存
        this.redisUtils.set(systemCacheConfig.getUserCacheName(), JSON.toJSONString(users));

        // endregion

        return ActionResult.ok();
    }

    //endregion

    //region 获取在线用户

    @GetMapping("/GetOnlineUsers")
    @ApiOperation(value = "获取在线用户")
    @Log(OperationType = OperationType.QueryList)
    @Permission(permission = "user:query:onlineUsers")
    public QueryResult<SysUserDTO> getOnlineUsers() throws ExecutionException, InterruptedException {
        CompletableFuture<QueryResult<SysUserDTO>> future =
                CompletableFuture.supplyAsync(this.userService::queryOnlineUsers);
        return future.get();
    }

    //endregion

    //region 导入用户信息

    @PostMapping("/Import")
    @ApiOperation(value = "导入用户信息")
    @Log(OperationType = OperationType.ImportData)
    @Permission(permission = "user:import:entities")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ActionResult importUsers(MultipartFile file, String orgId) throws Exception {
        ActionResult actionResult = new ActionResult();
        int errorCount = 0;
        //region 常规合法性校验

        String id = UUID.randomUUID().toString();
        String filePath = RuYiFileUtil.saveMultipartFile(file, id);
        ImportConfigDTO configDTO = this.importConfigService.getImportConfig("UserImportConfig");
        configDTO.setExcelPath(filePath);
        errorCount = configDTO.validationDetecting();

        //endregion
        if (errorCount > 0) {
            //region 常规校验出不合规项

            actionResult.setObject(errorCount);
            id = FileNameUtil.getName(configDTO.getExcelPath()).split("\\.")[0];
            actionResult.setMessage(id);

            //endregion
        } else {
            //region 执行业务校验

            List<SysUser> allUsers = this.userService.queryAllUsers();

            FileInputStream fileStream = new FileInputStream(configDTO.getExcelPath());
            Workbook workbook = new HSSFWorkbook(fileStream);
            Sheet worksheet = workbook.getSheetAt(0);

            for (int i = configDTO.getStartRow(); i <= worksheet.getLastRowNum(); i++) {
                String logonName = RuYiPoiUtil.getCellValue(worksheet.getRow(i).getCell(2)).trim();
                if (!StringUtils.isEmpty(logonName) &&
                        allUsers.stream().anyMatch(t -> t.getLogonName().equals(logonName))) {
                    errorCount++;
                    RuYiPoiUtil.setCellComment(worksheet, i, 2, "用户已存在！");
                }
            }

            //endregion
            if (errorCount > 0) {
                //region 常规校验出不合规项

                id = UUID.randomUUID().toString();
                String path = configDTO.getExcelPath();
                configDTO.setExcelPath(RuYiFileUtil.copyFile(path, id));

                FileOutputStream outputStream = new FileOutputStream(configDTO.getExcelPath());
                workbook.write(outputStream);

                workbook.close();
                outputStream.close();
                fileStream.close();

                actionResult.setObject(errorCount);
                actionResult.setMessage(id);

                //endregion
            } else {
                //region 执行数据导入

                //region 读取表单数据

                InputStream inputStream = file.getInputStream();
                ExcelReader reader = ExcelUtil.getReader(inputStream);

                HashMap<String, String> headerAlias = new HashMap<>(6);
                headerAlias.put("用户姓名", "displayName");
                headerAlias.put("登录账号", "logonName");
                headerAlias.put("性别", "sex");
                headerAlias.put("手机号", "mobilephone");
                headerAlias.put("座机号", "telephone");
                headerAlias.put("电子邮件", "email");
                reader.setHeaderAlias(headerAlias);

                List<SysUserExcelDTO> list = reader.readAll(SysUserExcelDTO.class);

                List<SysUser> sysUsers = new ArrayList<>();
                String defaultPassword = this.systemConfig.getDefaultPassword();
                String aesKey = this.systemConfig.getAesKey();

                list.forEach(item -> {
                    SysUser user = new SysUser();
                    user.setDisplayName(item.getDisplayName());
                    user.setLogonName(item.getLogonName());
                    switch (item.getSex()) {
                        case "男":
                            user.setSex(0);
                            break;
                        case "女":
                            user.setSex(1);
                            break;
                        case "第三性别":
                            user.setSex(2);
                            break;
                    }
                    user.setMobilephone(item.getMobilephone());
                    user.setTelephone(item.getTelephone());
                    user.setEmail(item.getEmail());
                    String salt = UUID.randomUUID().toString();
                    user.setSalt(salt);
                    user.setPassword(RuYiAesUtil.encrypt(defaultPassword + salt, aesKey));
                    user.setIsEnabled(YesNo.YES.ordinal());
                    sysUsers.add(user);
                });

                //endregion

                //region 保存到数据库中

                this.userService.saveBatch(sysUsers);

                List<SysOrgUser> listOrgUser = new ArrayList<>();
                sysUsers.forEach(item -> {
                    SysOrgUser orgUser = new SysOrgUser();
                    orgUser.setUserId(item.getId());
                    orgUser.setOrgId(orgId);
                    listOrgUser.add(orgUser);
                });
                //保存机构与角色关系
                this.orgUserService.saveBatch(listOrgUser);

                //endregion

                //region 数据一致性维护

                Object value = this.redisUtils.get(systemCacheConfig.getUserCacheName());
                List<SysUserDTO> users = JSON.parseArray(value.toString(), SysUserDTO.class);

                value = this.redisUtils.get(this.systemCacheConfig.getOrgCacheName());
                List<SysOrganizationDTO> orgs = JSON.parseArray(value.toString(), SysOrganizationDTO.class);

                String orgName = orgs.stream()
                        .filter(t -> t.getId().equals(orgId))
                        .collect(Collectors.toList())
                        .get(0)
                        .getOrgName();

                sysUsers.forEach(user -> {
                    SysUserDTO userDTO = this.modelMapper.map(user, SysUserDTO.class);
                    userDTO.setOrgId(orgId);
                    userDTO.setOrgName(orgName);
                    users.add(userDTO);
                });

                //更新用户缓存
                this.redisUtils.set(systemCacheConfig.getUserCacheName(), JSON.toJSONString(users));

                //endregion

                //endregion
            }
        }
        actionResult.setHttpStatusCode(HttpStatus.OK.value());
        return actionResult;
    }

    //endregion

    //region 导出用户信息

    @GetMapping("/ExportExcel")
    @ApiOperation(value = "导出用户信息")
    @Log(OperationType = OperationType.ExportData)
    @Permission(permission = "user:import:entities")
    public void export(HttpServletResponse response) throws Exception {
        Object value = this.redisUtils.get(systemCacheConfig.getUserCacheName());
        List<SysUserDTO> users = JSON.parseArray(value.toString(), SysUserDTO.class);

        SysUserDTO currentUser = this.sessionContext.getCurrentUserInfo();
        if (currentUser.getIsSupperAdmin() == YesNo.NO.ordinal()) {
            String orgId = this.sessionContext.getUserOrgId();
            users = users.stream()
                    .filter(t -> !StringUtils.isEmpty(t.getOrgId()))
                    .filter(t -> t.getOrgId().equals(orgId))
                    .sorted(Comparator.comparing(SysUserDTO::getSerialNumber))
                    .collect(Collectors.toList());
        }

        // 在内存操作，写出到浏览器
        ExcelWriter writer = ExcelUtil.getWriter(false);
        //自定义标题别名
        writer.addHeaderAlias("logonName", "用户账号");
        writer.addHeaderAlias("displayName", "用户姓名");
        writer.addHeaderAlias("telephone", "座机号");
        writer.addHeaderAlias("mobilephone", "手机号");
        writer.addHeaderAlias("email", "电子邮件");
        writer.addHeaderAlias("sex", "性别");
        writer.addHeaderAlias("remark", "备注");
        writer.addHeaderAlias("createTime", "创建时间");

        writer.setOnlyAlias(true);
        // 一次性写出list内的对象到excel，使用默认样式，强制输出标题
        writer.write(users, true);

        Sheet sheet = writer.getSheet();
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            double sex = sheet.getRow(i).getCell(5).getNumericCellValue();
            if (sex == 0) {
                sheet.getRow(i).getCell(5).setCellValue("男");
            } else if (sex == 1) {
                sheet.getRow(i).getCell(5).setCellValue("女");
            } else {
                sheet.getRow(i).getCell(5).setCellValue("第三性别");
            }
        }

        // 设置浏览器响应的格式
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("用户信息", StandardCharsets.UTF_8);
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        out.close();
        writer.close();
    }

    //endregion

}
